_ = require 'lodash'

error = require '../error'
log = require '../log'
mysql = require '../storage/Mysql'
Meta = require '../meta/Meta'

toDupKeyError = (e, entityMeta)->
    matches = e.message.match(/Duplicate entry '(.*)' for key '(.+)'$/)
    if matches
        # value = matches[1]
        key = matches[2]
        specifiedKey = entityMeta.tableName + "_" + key
        indexConfig = _.find entityMeta.mysqlIndexes, (i)-> i.name == specifiedKey
        message = indexConfig?.errorMessage || "值重复：#{key}"
        {code: "DupKey", message, key}
    else
        {code: "DupKey", message: e.message, key: null}

exports.gCreate = (ctx, entityMeta, instance)->
    return null unless _.size(instance)

    id = Meta.newObjectId().toString()
    instance._id = id

    try
        yield from ctx.conn.gInsertOne entityMeta.tableName, instance
        id
    catch e
        throw e unless mysql.isIndexConflictError(e)
        {code, message} = toDupKeyError(e, entityMeta)
        throw new error.UniqueConflictError(code, message)

# 全量/部分更新一个或多个
exports.gUpdateMany = (ctx, entityMeta, idVersions, instance)->
    return unless idVersions?.length
    return unless _.size(instance)
    try
        for idVersion in idVersions
            criteria = {_id: idVersion._id, _version: idVersion._version}
            instance._version = idVersion._version + 1
            r = yield from ctx.conn.gUpdateByObject entityMeta.tableName, criteria, instance
            log.debug 'sql update result', r
            if r?.changedRows != 1 # 还有一个affectedRows
                throw new error.UserError 'ConcurrentUpdate'
    catch e
        throw e unless mysql.isIndexConflictError(e)
        {code, message} = toDupKeyError(e, entityMeta)
        throw new error.UniqueConflictError(code, message)

# 批量删除
exports.gRemoveMany = (ctx, entityMeta, ids)->
    return unless ids?.length
    if entityMeta.removeMode == 'toTrash'
        yield from gRemoveManyToTrash(ctx, entityMeta, ids)
    else
        yield from gRemoveManyCompletely(ctx, entityMeta, ids)

# 批量找回
exports.gRecoverMany = (ctx, entityMeta, ids)->
    return unless ids?.length
    trashTable = Meta.getCollectionName(entityMeta, "trash")

    list = yield from conn.gListByIds trashTable, ids
    for entity in list
        entity.modifiedOn = new Date()
        entity._version++

    yield from ctx.conn.gInsertMany entityMeta.tableName, list # TODO 主键重复？
    yield from ctx.conn.gDeleteManyByIds trashTable, ids

exports.gFindOneByCriteria = (ctx, repo, entityMeta, criteria, includedFields)->
    table = Meta.getCollectionName entityMeta, repo

    list = yield from ctx.conn.gFind {table, criteria, includedFields, pageNo: 1, pageSize: 1}
    list.length && list[0] || null

# 带分页信息
exports.gList = (ctx, {repo, entityMeta, criteria, includedFields, sortCriteria, pageNo, pageSize, withoutTotal})->
    table = Meta.getCollectionName entityMeta, repo

    yield from ctx.conn.gFind {table, criteria, includedFields, sortCriteria, pageNo, pageSize, paging: withoutTotal}

gRemoveManyToTrash = (ctx, entityMeta, ids) ->
    return unless ids?.length
    trashTable = Meta.getCollectionName(entityMeta, "trash")

    list = yield from conn.gListByIds entityMeta.tableName, ids
    for entity in list
        entity.modifiedOn = new Date()
        entity._version++

    if list?.length
        yield from ctx.conn.gInsertMany trashTable, list # TODO 主键重复？
    yield from ctx.conn.gDeleteManyByIds entityMeta.tableName, ids

gRemoveManyCompletely = (ctx, entityMeta, ids) ->
    return unless ids?.length
    yield from ctx.conn.gDeleteManyByIds entityMeta.tableName, ids
